/*
 * @(#)HypertextUnitBuilder.java	1.0 05/01/07
 *
 * Copyright 2007 Fabio Gasparetti. All rights reserved.
 */
package org.tabularium.text.html;

import java.util.Iterator;

/**
 * Extracts an <code>HypertextUnit</code>-based representation from HTML
 * pages.
 * <p>
 * This abstract class's implementations shouldn't tokenize text and normalize
 * links.
 * <p>
 * Usually, implementations are based on html parsing libraries, such as
 * Apache's Xerces or SourceForge's htmlparser.
 * 
 * @author Fabio Gasparetti
 * @version 1.0, 05/01/07
 */

public abstract class HypertextUnitBuilder {
	/**
	 * Default Html delimitators of units without related closing elements (or
	 * the closing elements are not relevant for rendering).
	 * <p>
	 * Usually these tags refer to fine-grained html formatting, therefore the
	 * tree structure should only be partially affected.
	 * <p>
	 * For each <tt>HTML-DELIM</tt> tag, a new HypertextUnit object is added
	 * to the content of the current node. The <tt>HTML-DELIM</tt> tags do not
	 * have any content, so they do not increase the tree depth.
	 * <p>
	 * The text related to these tags, e.g.,
	 * <code>&lt;p&gt;<em>dummy text</em>&lt;/p&gt;</code> is saved into a
	 * distinct HypertextUnit that follows the the delimitator's node. <br>
	 * For example, for a
	 * <code>&lt;TR&gt; <em>dummy-text</em> &lt;HR&gt; <em>dummy-text</em> &lt;/TR&gt;</code>
	 * sequence we have:<br>
	 * <tt>[... [TR [TEXT-UNIT, HR, TEXT-UNIT] ...]</tt>
	 */
	public static final String[] DEFAULT_HTML_DELIM = { "HR", "P"
	/* "BR" ignoring breaks */};

	/**
	 * Default Html deliminators of units with optional closing elements, e.g.,
	 * list's items <code>&lt;LI&gt;<code>.
	 * <p>
	 * For each <tt>HTML-UNIT-DELIM</tt> tag, a new HypertextUnit object is created as
	 * a child of the current node, increasing the tree depth.
	 * <p> 
	 * The text related to these tags has to be found in the tag's content, 
	 * for example:<br> <tt>[... UL [LI [TEXT-UNIT] LI... ]]</tt>.
	 * <p>
	 * The tag's content ends when another
	 * <tt>HTML-UNIT-DELIM</tt> or a <tt>HTML-UNIT-DBL-DELIM</tt> tag is encountered.
	 */
	public static final String[] DEFAULT_HTML_UNIT_DELIM = { "LI", "DT"
	/* "DD" ignoring definition-description difference */};

	/**
	 * Default Html deliminators tags with a mandatory closing element.
	 * <p>
	 * For each <tt>HTML-UNIT-DBL-DELIM</tt> tag, a new HypertextUnit object
	 * is created as a child of the current node, increasing the tree depth.
	 * <p>
	 * The optional text related to these tags has to be found in the tag's
	 * content, for example:<br>
	 * <tt>[... TR [TEXT-UNIT] ...]</tt>.
	 * <p>
	 * The tag's content ends when the corresponding end teg is found.
	 * <p>
	 * Somelibraries (e.g., htmlparser) ensures to adjust Web pages with missing
	 * closing tags.
	 * <p>
	 * Beware of including the main tags, HEAD, BODY and HTML, or the method
	 * <code>HypertextUnit.toHTML()</code> is not able to correctly rebuild
	 * pages.
	 * <p>
	 * SPAN is not usually included because is considered an in-line tag used
	 * for a small chunk of in-line HTML (whereas a div element is block-line,
	 * which is basically equivalent to having a line-break before and after
	 * it).
	 */
	public static final String[] DEFAULT_HTML_UNIT_DBL_DELIM = { "TABLE", "TH", "TR",
		"TD", "DIV", "SPAN", "UL", "OL", "DL", "HEAD", "BODY", "HTML",
		"H1", "H2", "H3", "H4", "H5", "H6" };

	protected String[] htmlDelim = DEFAULT_HTML_DELIM;

	protected String[] htmlUnitDelim = DEFAULT_HTML_UNIT_DELIM;

	protected String[] htmlUnitDblDelim = DEFAULT_HTML_UNIT_DBL_DELIM;

	/**
	 * Returns the root of a tree that represents a given Web page. The tree is
	 * composed of a <code>HypertextUnit</code> objects or some sub-class
	 * provided by <code>HypertextUnitFactory</code>.
	 * 
	 * Note: page's links are normalized (see the
	 * {@org.tabularium.net.UrlNormalizer} class).
	 */
	public abstract HypertextUnit build(String url, String htmltext,
			HypertextUnitFactory unitFactory) throws Exception;

	/**
	 * Call it before building the tree to avoid inconsistencies.
	 */
	public void setHtmlDelim(String[] delim) {
		htmlDelim = delim;
	}

	/**
	 * Call it before building the tree to avoid inconsistencies.
	 */
	public void setHtmlUnitDelim(String[] delim) {
		htmlUnitDelim = delim;
	}

	/**
	 * Call it before building the tree to avoid inconsistencies.
	 */
	public void setHtmlUnitDblDelim(String[] delim) {
		htmlUnitDblDelim = delim;
	}

	public String[] getHtmlDelim() {
		return htmlDelim;
	}

	public String[] getHtmlUnitDelim() {
		return htmlUnitDelim;
	}

	public String[] getHtmlUnitDblDelim() {
		return htmlUnitDblDelim;
	}

	/**
	 * Assigns ids to a tree.
	 * 
	 * @see HypertextUnit
	 */
	protected static HypertextUnit assignIds(HypertextUnit root) {
		recursiveAssignIds(root, 0);
		return root;
	}

	protected static void recursiveAssignIds(HypertextUnit root, int depth) {
		if (root == null)
			return;
		if (depth == 0) {
			root.id = new String("0");
		}
		Iterator iter = root.content.iterator();
		int id = 0;
		while (iter.hasNext()) {
			HypertextUnit unit = (HypertextUnit) iter.next();
			unit.id = new String(root.id + ":" + id++);
			recursiveAssignIds(unit, depth + 1);
		}
	}

}
